package ro.ubbcluj.cs.damate.plugin.ui.dialogs;

import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;

import ro.ubbcluj.cs.damate.plugin.DamateActivator;
import ro.ubbcluj.cs.damate.plugin.services.AuthenticationService;

public class LoginDialog extends Dialog {

    private Text usernameText;
    private Text passwordText;
    private Label errorMessageLabel;
    private String username;
    private String password;

    private static LoginDialog loginDialog;
    private AuthenticationService authenticationService;

    private LoginDialog(AuthenticationService authenticationService) {
        super(Display.getDefault().getActiveShell());
        this.authenticationService = authenticationService;
    }

    public static LoginDialog getLoginDialog(AuthenticationService authenticationService) {
        if (loginDialog == null) {
            loginDialog = new LoginDialog(authenticationService);
        }
        loginDialog.create();
        return loginDialog;
    }

    @Override
    public void create() {
        super.create();
    }


    protected void configureShell(Shell shell) {
        super.configureShell(shell);
        shell.setText("Login");
        shell.setImage(DamateActivator.getImageDescriptor("/resources/images/icons/icon.png").createImage());
    }


    @Override
    protected Control createDialogArea(Composite parent) {
        GridLayout layout = new GridLayout();
        layout.numColumns = 1;
        parent.setLayout(layout);

        GridLayout headerLayout = new GridLayout();
        headerLayout.numColumns = 1;
        headerLayout.marginLeft = 30;
        headerLayout.marginRight = 30;
        GridData headerData = new GridData();
        headerData.horizontalAlignment = GridData.CENTER;
        Composite header = new Composite(parent, SWT.NONE);
        header.setLayout(headerLayout);
        header.setLayoutData(headerData);
        Label logo = new Label(header, SWT.NONE);
        logo.setImage(DamateActivator.getImageDescriptor("/resources/images/logo.png").createImage());

        GridLayout contentLayout = new GridLayout();
        contentLayout.numColumns = 2;
        contentLayout.horizontalSpacing = 20;
        contentLayout.marginLeft = 30;
        contentLayout.marginRight = 30;
        GridData bodyData = new GridData();
        bodyData.horizontalAlignment = GridData.FILL;
        Composite body = new Composite(parent, SWT.NONE);
        body.setLayout(contentLayout);
        body.setLayoutData(bodyData);

        // The text fields will grow with the size of the dialog
        GridData gridData = new GridData();
        gridData.grabExcessHorizontalSpace = true;
        gridData.horizontalAlignment = GridData.FILL;


        Label label1 = new Label(body, SWT.NONE);
        label1.setText("Username");

        usernameText = new Text(body, SWT.BORDER);
        usernameText.setLayoutData(gridData);
        if (username != null) {
        	usernameText.setText(username);
        }

        Label label2 = new Label(body, SWT.NONE);
        label2.setText("Password");
        // You should not re-use GridData
        gridData = new GridData();
        gridData.grabExcessHorizontalSpace = true;
        gridData.horizontalAlignment = GridData.FILL;
        passwordText = new Text(body, SWT.BORDER);
        passwordText.setLayoutData(gridData);
        if (password != null) {
        	passwordText.setText(password);
        }

        GridData errorMsgData = new GridData();
        errorMsgData.horizontalAlignment = GridData.CENTER;
        errorMsgData.horizontalSpan = 2;

        errorMessageLabel = new Label(body, SWT.NONE);
        errorMessageLabel.setForeground(parent.getDisplay().getSystemColor(SWT.COLOR_RED));
        errorMessageLabel.setVisible(false);
        errorMessageLabel.setText("Invalid username or password!");
        errorMessageLabel.setLayoutData(errorMsgData);
        return parent;
    }

    @Override
    protected void createButtonsForButtonBar(Composite parent) {
        GridData gridData = new GridData();
        gridData.verticalAlignment = GridData.FILL;
        gridData.horizontalSpan = 3;
        gridData.grabExcessHorizontalSpace = true;
        gridData.grabExcessVerticalSpace = true;
        gridData.horizontalAlignment = SWT.CENTER;

        parent.setLayoutData(gridData);
        // Create Add button
        // Own method as we need to overview the SelectionAdapter
        createOkButton(parent, OK, "Login", true);
        // Add a SelectionListener

        // Create Cancel button
        Button cancelButton = createButton(parent, CANCEL, "Cancel", false);
        // Add a SelectionListener
        cancelButton.addSelectionListener(new SelectionAdapter() {
            public void widgetSelected(SelectionEvent e) {
                setReturnCode(CANCEL);
                close();                
            }
        });
    }

    protected Button createOkButton(Composite parent, int id, String label, boolean defaultButton) {
        // increment the number of columns in the button bar
        ((GridLayout) parent.getLayout()).numColumns++;
        Button button = new Button(parent, SWT.PUSH);
        button.setText(label);
        button.setFont(JFaceResources.getDialogFont());
        button.setData(new Integer(id));
        button.addSelectionListener(new SelectionAdapter() {
            public void widgetSelected(SelectionEvent event) {
                if (isValidInput()) {
                    okPressed();
                }
            }
        });
        if (defaultButton) {
            Shell shell = parent.getShell();
            if (shell != null) {
                shell.setDefaultButton(button);
            }
        }
        setButtonLayoutData(button);
        return button;
    }

    private boolean isValidInput() {
        boolean valid = true;
        if (usernameText.getText().length() == 0) {
            errorMessageLabel.setText("Invalid username or password!");
            errorMessageLabel.setVisible(true);
            valid = false;
        }
        if (passwordText.getText().length() == 0) {
            errorMessageLabel.setText("Invalid username or password!");
            errorMessageLabel.setVisible(true);
            valid = false;
        }
        return valid;
    }

    @Override
    protected boolean isResizable() {
        return true;
    }

    @Override
    public boolean close() {
        loginDialog = null;
        authenticationService.onLoginDialogClose();
        return super.close();
    }

    // Coyy textFields because the UI gets disposed
    // and the Text Fields are not accessible any more.
    private void saveInput() {
        username = usernameText.getText();
        password = passwordText.getText();
    }

    @Override
    protected void okPressed() {
        saveInput();
        int statusCode = authenticationService.authenticate(username, password);
        if (statusCode == 200) {
            super.okPressed();
        } else if (statusCode == 404) {
            errorMessageLabel.setText("Invalid username or password!");
            errorMessageLabel.setVisible(true);
        } else if (statusCode == 401) {
            errorMessageLabel.setText("This user has no login right!");
            errorMessageLabel.setVisible(true);
        } else {
            errorMessageLabel.setText("Unknown error! Try again later.");
            errorMessageLabel.setVisible(true);
        }
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }
}